前一天,我們再Service Worker中,導入IndexedDB API來存取文章,但是我們少改在app.js中,fetch cache API資源的部分。
但是,重複在兩個地方寫idb.open和put等方法,並不是很理想。
昨天有提到importScript()可以匯入函式庫,那麼就抽成一個檔案,在透過import匯入要使用的IndexedDB功能。
檔名不限定,但在此我就命名為indexedDB.js
var dbPromise = idb.open('articles', 1, function(db){
if(!db.objectStoreNames.contains('article'))
db.createObjectStore('article', {keyPath: 'id'});
});
將Service Worker中的open貼到indexedDB.js。
在Service Worker,匯入檔案。
importScripts('/src/js/indexedDB.js');
function writeData(table,data){
return dbPromise
.then(function(db){
var transaction = db.transaction(table, 'readwrite');
var article = transaction.objectStore(table);
article.put(data);
return transaction.complete;
});
}
在fetch事件寫的put抽成function
fetch(event.request)
.then(function(response){
var copyRes = response.clone();
copyRes.json()
.then(function(data){
for(var key in data){
writeData('article',data[key]);
}
})
})
接著Service Worker就可以直接丟參數近function。
原本資源都是放進cache,Service Worker對文章的處理已經轉移到IndexedDB,
所以前面fetch文章的內容,也要改詢問IndexedDB有沒有文章。
if ('indexedDB' in window){
readAllData('article')
.then(function(data){
if(!dataFromNetwork){
console.log('IndexedDB Data',data);
updateArticles(data);
}
});
}
readAllData()是下面在indexedDB.js寫的一支取article中,
所有文章內容的功能。
function readAllData(table){
return dbPromise
.then(function(db){
var transaction = db.transaction(table, 'readonly');
var store = transaction.objectStore(table);
return store.getAll();
});
}
這邊因為我只需要讀取Store中的資料,
在transaction中,只需要設定readonly,並回傳getAll(),取得所有內容。

看到Console視窗,會看到我們設定的訊息,成功執行Indexed Data,表示成功囉。
接著,測試離線網頁的反應。
這時候,在IndexedDB中看到first-post的image,是一串firebase上的url,
但沒網路情況下,圖片一樣成功載入,為什麼呢?
因為在fetch時後,資源已經Cache到dynamic的紀錄裡面。
到目前為止,從Cache API轉移到IndexedDB似乎沒什麼問題呢!![]()